import sys
import os
import time
# LED类
class LED:
    GPIO = "/sys/class/gpio"
    # 文件写入
    @staticmethod
    def __writeSysfs(dir: str, filename: str, value: str) -> None:
        try:
            os.system(f"echo {value} > {dir}/{filename}")
            # with open(f"{dir}/{filename}", mode="w", encoding="utf-8") as f:
            #     f.write(value)
        except Exception as e:
            sys.stderr.write(str(e) + '\n')
            raise e

    # 构造函数
    def __init__(self, num: int) -> None:
        print(f"init LED{num}")
        self.gpiopath = f"{LED.GPIO}/gpio{num}"
        self.gpionum = num
        try:
            # 当 /sys/class/gpio/gpio* 不存在时，export
            if not os.path.exists(self.gpiopath):
                LED.__writeSysfs(LED.GPIO, "export", f"{num}")
        except Exception:
            sys.stderr.write(f"Well, there is something wrong\n")

    # 析构函数
    def __del__(self) -> None:
        print(f"destory LED{self.gpionum}")
        try:
            # 当 /sys/class/gpio/gpio* 存在时，unexport
            if os.path.exists(self.gpiopath):
                self.turnOFF()
                LED.__writeSysfs(LED.GPIO, "unexport", f"{self.gpionum}")
            ##
            # 在__del__中调用open()会出错，不知道为什么，所以改用echo
                # os.system(f"echo '{self.gpionum}' > {LED.GPIO}/unexport")
        except Exception:
            sys.stderr.write(f"Well, there is something wrong\n")
    
    # 开灯
    def turnON(self) -> None:
        print(f"turn on LED{self.gpionum}")
        try:
            LED.__writeSysfs(self.gpiopath, "value", "1")
        except Exception:
            sys.stderr.write("fail to turnON, please check\n")
    # 关灯
    def turnOFF(self) -> None:
        print(f"turn off LED{self.gpionum}")
        try:
            LED.__writeSysfs(self.gpiopath, "value", "0")
        except Exception:
            sys.stderr.write("fail to turnOFF, please check\n")
            
    # 返回当前状态
    def getState(self) -> str:
        with open(f"{self.gpiopath}/value", mode="r", encoding="utf-8") as f:
            state = f.read()
        return state
    
    # 输出当前状态
    def dispState(self):
        print(f"LED{self.gpionum} value is {self.getState()}")

# LED工厂类
class LEDFactory:
    # 存放已经创建的对象
    cache={}
    
    @staticmethod
    def getLED(num:int)->LED:
        # 如果LED(num)不在cache中，构造并放入cache；在的话，直接返回
        # 系统资源唯一，所以每种LED对象全局唯一，要避免重复构造
        if num not in LEDFactory.cache:
            LEDFactory.cache[num] = LED(num)
            time.sleep(1)
        return LEDFactory.cache[num]